//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;
using OpenLS.Spreadsheet.Expressions;

namespace OpenLS.Spreadsheet.Formats.Biff.Tokens
{
    internal sealed class Area3DToken : FormulaToken
    {
        private readonly AccessorType _type;

        public Area3DToken(AccessorType type)
        {
            _type = type;
        }
        public override FormulaTokenId TokenId
        {
            get { switch (_type)
            {
                case AccessorType.Reference:
                    return FormulaTokenId.Area3d;
                    case AccessorType.Array:
                    return FormulaTokenId.Area3dA;
                    case AccessorType.Value:
                    return FormulaTokenId.Area3dV;
                default: throw new NotSupportedException();
            }}
        }

        private RangeReferenceAddress _rangeAddress;
        private ushort _sheetId;

        public Area3DToken(AccessorType type,ushort sheetId,  RangeReferenceAddress rangeReferenceAddress)
        {
            this._type = type;
            this._sheetId = sheetId;
#if DEBUG
            if (_sheetId == 1)
            Debug.WriteLine("Setting _sheetId to 1");
#endif
            this._rangeAddress = rangeReferenceAddress;
        }

        public override ushort GetLength(FormulaReadContextType context)
        {
            switch (context)
            {
                case FormulaReadContextType.Default:
                    return 10;
                case FormulaReadContextType.ExternName:
                    return 12;
                    default: throw new NotSupportedException();
            }
        }
        internal override void ReadContent(FormulaReadContext context)
        {
            _sheetId = context.ReadUInt16();
#if DEBUG
//                Debug.WriteLine("reading _sheetId = " + _sheetId);
#endif
            _rangeAddress = AddressHelper.ReadRangeReferenceAddress16(context);
        }
        internal override Expression GetExpression(FormulaEvaluationContext context)
        {
#if DEBUG
            
#endif
            var ws = context.WorkbookContext.GetExternalSheet(_sheetId);
            if (ws == null)
                return new ErrorExpression(Errors.RefError);
            //var ws = context.Workbook.Sheets[_sheetId] as Worksheet;
            RangeReference rr = new MultiCellsRangeReference(
                _rangeAddress.First.ToReference(ws),
                _rangeAddress.Last.ToReference(ws));
            return new RangeReferenceExpression(rr, context.Worksheet);
        }

        public override void WriteContent(FormulaWriteContext context)
        {
#if DEBUG
            Contract.Assert(context.HasSheetId(_sheetId));
#endif
           context.WriteUInt16(_sheetId);
            AddressHelper.WriteRangeReferenceAddress16(_rangeAddress, context);
        }
    }
}